%{

/*

This reads a DMIS input file and writes it out again after making the
changes described in the in-line comments below. There are two lexer
states, INITIAL and INSTRING.

This rounds numbers to six decimal places and then suppresses all
but one trailing zeros, which is what the parsers do.

*/

#ifdef _WIN32
 //don't include unistd.h because windows doesn't have it
 #define YY_NO_UNISTD_H
 //windows doesn't have isatty either
 #define isatty( x ) (0)
#endif

  int n;

%}

A [aA]
B [bB]
C [cC]
D [dD]
E [eE]
F [fF]
G [gG]
H [hH]
I [iI]
J [jJ]
K [kK]
L [lL]
M [mM]
N [nN]
O [oO]
P [pP]
Q [qQ]
R [rR]
S [sS]
T [tT]
U [uU]
V [vV]
W [wW]
X [xX]
Y [yY]
Z [zZ]
_ [\t ]

%x INSTRING


%%

^{_}*"$$".*\r\n  // delete lines starting with $$

"$"{_}*\r\n      // remove endlines after $ to join continued lines

^{_}*\r\n        // remove blank lines

,{_}*"05.1"{_}*\r\n {printf(",05.1\r\n");} // leave leading 0 in version number
,{_}*"05.2"{_}*\r\n {printf(",05.2\r\n");} // leave leading 0 in version number
,{_}*"05.1"{_}*,    {printf(",05.1,");}    // leave leading 0 in version number
,{_}*"05.2"{_}*,    {printf(",05.2,");}    // leave leading 0 in version number

"."{A}{N}{D}"."        {printf(".AND.");}   // echo dot words
"."{E}{Q}"."           {printf(".EQ.");}    // these rules are needed to
"."{F}{A}{L}{S}{E}"."  {printf(".FALSE.");} // prevent confusion between
"."{G}{E}"."           {printf(".GE.");}    // dots in dot words and
"."{G}{T}"."           {printf(".GT.");}    // decimal points in numbers
"."{L}{E}"."           {printf(".LE.");}
"."{L}{T}"."           {printf(".LT.");}
"."{N}{E}"."           {printf(".NE.");}
"."{N}{O}{T}"."        {printf(".NOT.");}
"."{O}{R}"."           {printf(".OR.");}
"."{T}{R}{U}{E}"."     {printf(".TRUE.");}

" "/("."[0-9])         {putchar('0');    // if space precedes a number
                                         // starting with a decimal point
                                       } // replace space with 0

[^0-9']/("."[0-9])     {putchar(yytext[0]); // if non-digit precedes a number
                        putchar('0');       // starting with a decimal point,
                                          } // add 0 before the decimal point

([0-9]".")/[^0-9]      {putchar(yytext[0]);  // insert 0 after decimal
                        putchar('.');        // point preceded by digit
                        putchar('0');}       // and followed by non-digit

"."[0-9]+/[^0-9]       {for (n=(yyleng-1); yytext[n] == '0'; n--);
                        if (n > 6)
			  { // crude rounding to six decimal places
			    if ((yytext[7] > '4') && (yytext[6] < '9'))
			      yytext[6] = (yytext[6] + 1);
			    yytext[7] = 0;
			  }
			if (n == 0)       // suppress trailing zeros
			  yytext[2] = 0;  // except one after decimal point
			else
			  yytext[n+1] = 0;
			printf("%s", yytext);}

[0-9]+/"."        { for (n=0; yytext[n] == '0'; n++); // in number with decimal
                    if (n == yyleng)                  // point, suppress
		      n--;                            // leading zeros
                    printf("%s", (yytext+n));}

\r\n               {ECHO;} // echo endlines

'                  {ECHO; BEGIN INSTRING;} // change state on ' and print it

[a-z]              {putchar(yytext[0] + ('A' - 'a'));} // capitalize letters

{_}                // remove spaces and tabs outside of strings

.                  {ECHO;}  // echo all other single characters

<INSTRING>"$"\r\n  // remove endlines following $, to join lines together

<INSTRING>('')     {ECHO;} // if two ' in a row, print, do not change state

<INSTRING>'        {ECHO; BEGIN INITIAL;} // change state on ' and print it

<INSTRING>.        {ECHO;}  // echo all other single characters in strings

%%

int yywrap()
{
  return 1;
}

int main(
 int argc,
 char * argv[])
{
  yyin = fopen(argv[1], "rb");
  if (yyin == 0)
    {
      fprintf(stderr, "unable to open file %s for reading\n", argv[1]);
      exit(1);
    }
  yylex();
  fclose(yyin);
  return 0;
}
